#include <netinet/in.h>    // for sockaddr_in
#include <sys/types.h>    // for socket
#include <sys/socket.h>    // for socket
#include <stdio.h>        // for printf
#include <stdlib.h>        // for exit
#include <string.h>        // for bzero
#include <pthread.h>     //for thread

#define HELLO_WORLD_SERVER_PORT    6666 
#define LENGTH_OF_LISTEN_QUEUE 20
#define BUFFER_SIZE 1024
#define FILE_NAME_MAX_SIZE 512

int main(int argc, char **argv)
{
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int opt = 0;
    int server_socket = 0;
    socklen_t length;
    int new_server_socket;
    pthread_t thread;
    
    void *thread_function(void *arg);

    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htons(INADDR_ANY);
    server_addr.sin_port = htons(HELLO_WORLD_SERVER_PORT);

    server_socket = socket(PF_INET,SOCK_STREAM,0);
    if( server_socket < 0)
    {
        printf("Create Socket Failed!");
        exit(1);
    }

    opt =1;
    setsockopt(server_socket,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt));
    
    if( bind(server_socket,(struct sockaddr*)&server_addr,sizeof(server_addr)))
    {
        printf("Server Bind Port : %d Failed!", HELLO_WORLD_SERVER_PORT); 
        exit(1);
    }

    if ( listen(server_socket, LENGTH_OF_LISTEN_QUEUE) )
    {
        printf("Server Listen Failed!"); 
        exit(1);
    }
	
    while (1)
    {
        length = sizeof(client_addr);

        new_server_socket = accept(server_socket,(struct sockaddr*)&client_addr,&length);
        if ( new_server_socket < 0)
        {
            printf("Server Accept Failed!\n");
            break;
        }

        if(pthread_create(&thread, NULL, thread_function, &new_server_socket) != 0)
        {  
            printf("pthread_create Failed!\n");
            break;  
        }  
    }

    close(server_socket);
    return 0;
}

void *thread_function(void *arg)
{
    int new_server_socket;
    int file_block_length = 0;
    socklen_t length;
    FILE * fp = NULL;
    char buffer[BUFFER_SIZE];
    char file_name[FILE_NAME_MAX_SIZE+1];

    new_server_socket = *((int*)arg);
    bzero(buffer, BUFFER_SIZE);
    length = recv(new_server_socket,buffer,BUFFER_SIZE,0);
    if (length < 0)
    {
        printf("Server Recieve Data Failed!\n");
        return;
    }
    
    bzero(file_name, FILE_NAME_MAX_SIZE+1);
    strncpy(file_name, buffer, strlen(buffer)>FILE_NAME_MAX_SIZE?FILE_NAME_MAX_SIZE:strlen(buffer));

    printf("Client socket number: %d,  %s\n",new_server_socket, file_name);
    fp = fopen(file_name,"r");
    if(NULL == fp )
    {
        printf("File:\t%s Not Found\n", file_name);
    }
    else
    {
        bzero(buffer, BUFFER_SIZE);
        while( (file_block_length = fread(buffer,sizeof(char),BUFFER_SIZE,fp))>0)
        {
            printf("file_block_length = %d\n",file_block_length);

            if(send(new_server_socket,buffer,file_block_length,0)<0)
            {
                printf("Send File:\t%s Failed\n", file_name);
                break;
            }
            bzero(buffer, BUFFER_SIZE);
        }

        fclose(fp);
        printf("File:\t%s Transfer Finished\n",file_name);
    }

    close(new_server_socket);
}
